// import com.alibaba.druid.sql.ast.SQLExpr;
// import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
// import com.alibaba.druid.sql.ast.SQLReplaceable;
// import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;

// import java.util.Collections;
// import java.util.List;

#include "MySqlOrderingExpr.h"
#include "../../../../ast/SQLExpr.h"
#include "../../../../ast/SQLOrderingSpecification.h"
#include "../../visitor/MySqlASTVisitor.h"

MySqlOrderingExpr::MySqlOrderingExpr()
{
}

MySqlOrderingExpr::MySqlOrderingExpr(SQLExpr_ptr expr, SQLOrderingSpecification_ptr type) : MySqlExprImpl()
{
  setExpr(expr);
  this->type = type;
}

SQLObject_ptr MySqlOrderingExpr::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<MySqlOrderingExpr>(new MySqlOrderingExpr());
  std::shared_ptr<MySqlOrderingExpr> x = std::dynamic_pointer_cast<MySqlOrderingExpr>(clone_tmp);
  // MySqlOrderingExpr x = new MySqlOrderingExpr();
  if (expr != nullptr)
  {
    x->setExpr(std::dynamic_pointer_cast<SQLExpr>(expr->clone()));
  }
  x->type = type;
  return x;
}

// @Override
BOOL_ptr MySqlOrderingExpr::replace(SQLExpr_ptr expr, SQLExpr_ptr target)
{
  if (this->expr == expr)
  {
    setExpr(target);
    return BOOL::TRUE;
  }

  return BOOL::FALSE;
}

// @Override
void MySqlOrderingExpr::accept0(MySqlASTVisitor_ptr mysqlVisitor)
{
  if (mysqlVisitor->visit(SharedObject(MySqlOrderingExpr)))
  {
    if (expr != nullptr)
    {
      expr->accept(mysqlVisitor);
    }
  }

  mysqlVisitor->endVisit(SharedObject(MySqlOrderingExpr));
}

// @Override
SQLObject_list_ptr MySqlOrderingExpr::getChildren()
{
  SQLObject_list_ptr tmp = std::make_shared<std::list<SQLObject_ptr>>();
  tmp->push_back(this->expr);
  return tmp;
}

SQLExpr_ptr MySqlOrderingExpr::getExpr()
{
  return expr;
}

void MySqlOrderingExpr::setExpr(SQLExpr_ptr expr)
{
  if (expr != nullptr)
  {
    expr->setParent(SharedObject(MySqlOrderingExpr));
  }
  this->expr = expr;
}

SQLOrderingSpecification_ptr MySqlOrderingExpr::getType()
{
  return type;
}

void MySqlOrderingExpr::setType(SQLOrderingSpecification_ptr type)
{
  this->type = type;
}

// @Override
bool MySqlOrderingExpr::equals(Object_ptr obj)
{
  if (this == obj.get())
  {
    return true;
  }
  if (obj == nullptr)
  {
    return false;
  }
  if (getClass()->c_str() != obj->getClass()->c_str())
  {
    return false;
  }
  MySqlOrderingExpr_ptr other = std::dynamic_pointer_cast<MySqlOrderingExpr>(obj);
  if (expr != other->expr)
  {
    return false;
  }
  if (type == nullptr)
  {
    if (other->type != nullptr)
    {
      return false;
    }
  }
  else if (!(type->name->c_str() == other->type->name->c_str()))
  {
    return false;
  }
  return true;
}

// @Override
int MySqlOrderingExpr::hashCode()
{
  int prime = 31;
  int result = 1;
  result = prime * result + ((expr == nullptr) ? 0 : expr->hashCode());
  result = prime * result + ((type == nullptr) ? 0 : type->mask);
  return result;
}
